﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Text.RegularExpressions;
using AutoCADDotNetLibrary;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace Test
{
    public class XData
    {
        [PopMenuItem(1), MenuMacro("1.   添加XData")]
        [AcadPopupMenuItem("1.   添加XData", 1)]
        [CommandMethod("AddXData")]
        public void AddXData()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;

            using (Transaction trans = doc.TransactionManager.StartTransaction())
            {
                doc.Database.AddTableRecord<RegAppTableRecord>($"XData");

                List<TypedValue> code = new List<TypedValue>()
                {
                    { DxfCode.ExtendedDataAsciiString,"1" },
                    { DxfCode.ExtendedDataAsciiString,"2" },
                    { new TypedValue[]{ } },
                };

                ResultBuffer rf = new ResultBuffer()
                {
                    { DxfCode.ExtendedDataRegAppName,$"XData" },
                    { new TypedValue[]{ },null },
                    { code,null },
                };

                Line l = new Line(Point3d.Origin, new Point3d(100, 100, 0));
                l.XData = rf;
                doc.Database.AddEntityToSpace(l);

                trans.Commit();
            }
        }

        [PopMenuItem(2), MenuMacro("2.   删除XData")]
        [AcadPopupMenuItem("2.   删除XData", 2)]
        [CommandMethod("DeleteXData")]
        public void DeleteXData()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;

            using (Transaction trans = doc.TransactionManager.StartTransaction())
            {
                Entity ent = doc.Editor.Get<Entity>("选择实体") as Entity;
                if (ent == null)
                    return;

                ent.XData = new ResultBuffer()
                {
                    { DxfCode.ExtendedDataRegAppName,$"XData" },
                };

                trans.Commit();
            }
        }

        [PopMenuItem(3), MenuMacro("3.  ORM模型")]
        [AcadPopupMenuItem("3.   ORM模型", 3)]
        [CommandMethod("GetSetModel")]
        public void GetSetModel()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;

            using (Transaction trans = doc.TransactionManager.StartTransaction())
            {
                doc.Database.AddTableRecord<RegAppTableRecord>("Model");

                Line ent = new Line(new Point3d(0, 0, 0), new Point3d(10, 10, 0));

                Model setModel = new Model()
                {
                    p1 = "p1",
                    p2 = 222,
                    p3 = 333,
                    p4 = new string[] { "1", "2", "3" },
                    p5 = new List<int>() { 1, 2, 3, 4 },
                    p6 = new Point2d(0.2, 0.3),
                    p7 = new System.Windows.Thickness(11, 22, 33, 44),

                };
                ent.SetXdataByModel<Model>(setModel);

                //无法转化时，默认不出错，返回null
                Model getModel = ent.GetModelByXdata<Model>();

                doc.Database.AddEntityToSpace(ent);
                trans.Commit();
            }
        }

    }


    [RegAppORM("Model")]
    public class Model
    {
        [XDataORM(0)]
        public string p1 { get; set; } = "";

        //允许跳过1，但最好不要

        [XDataORM(2)]
        public int p2 { get; set; }

        [XDataORM(3, DxfCode = DxfCode.ExtendedDataInteger32)]
        public int p3 { get; set; }

        //数组，与项对应
        [XDataORM(4)]
        public string[] p4 { get; set; }

        //数组，与项对应
        [XDataORM(5, DxfCode = DxfCode.ExtendedDataInteger32)]
        public List<int> p5 { get; set; }

        //自定义类型装换器
        [XDataORM(6)]
        [TypeConverter(typeof(Point2dConverter))]
        public Point2d p6 { get; set; }

        //类上的转换器[TypeConverter(typeof(ThicknessConverter))]
        [XDataORM(7)]
        public System.Windows.Thickness p7 { get; set; }
    }

    public class Point2dConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return destinationType == typeof(Point2d);
        }
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            return $"Point2d({((Point2d)value).X},{((Point2d)value).Y})";
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            Match pt = Regex.Match((string)value, @"^Point2d\(([0-9|\.]*),([0-9|\.]*)\)$");
            if (pt.Success)
            {
                return new Point2d(double.Parse(pt.Groups[1].Value), double.Parse(pt.Groups[2].Value));
            }
            else
            {
                throw new System.Exception("点格式错误");
            }
        }
    }
}
